package ranking;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import utils.RankingConstant;
import utils.RepositoryUtils;

public class Player {
  private String name;
  private String firstname;
  private String ranking;
  private String futurRanking;
  private String rankingCalculate;
  private int rankPosition;
  private int points;
  private int maximumVictories;
  private int bonusVictories;
  private int defeatsSameRank;
  private int defeatsMinusOneRank;
  private int defeatsMinusTwoRank;
  private boolean isMale = true;
  private boolean isNC = false;
  private boolean isFourthSerie = false;
  private boolean isThirdSerie = false;
  private boolean isSecondSerie = false;
  private boolean isFirstSerie = false;
  private List<Opponent> victories = null;
  private List<Opponent> defeats = null;
  
  public int getBonusVictories() {
    return bonusVictories;
  }
  public void setBonusVictories(int bonusVictories) {
    this.bonusVictories = bonusVictories;
  }
  public int getDefeatsSameRank() {
    return defeatsSameRank;
  }
  public void setDefeatsSameRank(int defeatsSameRank) {
    this.defeatsSameRank = defeatsSameRank;
  }
  public int getDefeatsMinusOneRank() {
    return defeatsMinusOneRank;
  }
  public void setDefeatsMinusOneRank(int defeatsMinusOneRank) {
    this.defeatsMinusOneRank = defeatsMinusOneRank;
  }
  public int getDefeatsMinusTwoRank() {
    return defeatsMinusTwoRank;
  }
  public void setDefeatsMinusTwoRank(int defeatsMinusTwoRank) {
    this.defeatsMinusTwoRank = defeatsMinusTwoRank;
  }
  public String getRankingCalculate() {
    return rankingCalculate;
  }
  public void setRankingCalculate(String rankingCalculate) {
    this.rankingCalculate = rankingCalculate;
    
    calculateRankPosition();
  }
  public String getFuturRanking() {
    return futurRanking;
  }
  public void setFuturRanking(String futurRanking) {
    this.futurRanking = futurRanking;
    
    calculateRankPosition();
  }
  public int getMaximumVictories() {
    return maximumVictories;
  }
  public void setMaximumVictories(int maximumVictories) {
    this.maximumVictories = maximumVictories;
  }
  public boolean isNC() {
    return isNC;
  }
  public void setNC(boolean isNC) {
    this.isNC = isNC;
  }
  public boolean isFourthSerie() {
    return isFourthSerie;
  }
  public void setFourthSerie(boolean isFourthSerie) {
    this.isFourthSerie = isFourthSerie;
  }
  public boolean isThirdSerie() {
    return isThirdSerie;
  }
  public void setThirdSerie(boolean isThirdSerie) {
    this.isThirdSerie = isThirdSerie;
  }
  public boolean isSecondSerie() {
    return isSecondSerie;
  }
  public void setSecondSerie(boolean isSecondSerie) {
    this.isSecondSerie = isSecondSerie;
  }
  public boolean isFirstSerie() {
    return isFirstSerie;
  }
  public void setFirstSerie(boolean isFirstSerie) {
    this.isFirstSerie = isFirstSerie;
  }
  public List<Opponent> getVictories() {
    return victories;
  }
  public void setVictories(List<Opponent> victories) {
    this.victories = victories;
    recalculateOpponentPoint();
  }
  public List<Opponent> getDefeats() {
    return defeats;
  }
  public void setDefeats(List<Opponent> defeats) {
    this.defeats = defeats;
  }
  public int getPoints() {
    return points;
  }
  public void setPoints(int points) {
    this.points = points;
  }
  public boolean isMale() {
    return isMale;
  }
  public void setMale(boolean isMale) {
    this.isMale = isMale;
  }
  public int getRankPosition() {
    return rankPosition;
  }
  public void setRankPosition(int rankPosition) {
    this.rankPosition = rankPosition;
  }
  public String getRanking() {
    return ranking;
  }
  public void setRanking(String ranking) {
    this.ranking = ranking;
  }
  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getFirstname() {
    return firstname;
  }
  public void setFirstname(String firstname) {
    this.firstname = firstname;
  }

  public void buildPlayer(String ranking, String name, String firstname) {
    setRanking(ranking);
    setRankingCalculate(ranking);
    setFuturRanking(ranking);
    setName(name);
    setFirstname(firstname);
  }

  public void calculateMaximumVictories() {
    Integer maximumVictories = RepositoryUtils.HASHMAP_MAXIMUM_VICTORIES.get(rankingCalculate);
    setMaximumVictories(maximumVictories.intValue());
  }
  
  public void calculateBonusVictories() {
    int total = victories.size() - defeatsSameRank - 2 * defeatsMinusOneRank - 5 * defeatsMinusTwoRank;
    setBonusVictories(convertVictoriesToBonus(total));
  }
  
  protected void calculateRankPosition() {
    Integer rankPosition = RepositoryUtils.HASHMAP_RANK_POSITION.get(rankingCalculate);
    setRankPosition(rankPosition.intValue());
  }

  public void calculTotalPoint() {
    int totalPoint = 0;
    int maxVictories = 0;
    Collections.sort(victories, Opponent.OPPONENT_COMPARATOR);
    for (Iterator<Opponent> iterator = victories.iterator(); iterator.hasNext();) {
      Opponent opponent = (Opponent) iterator.next();
      if (!opponent.isWO()) {
        if (maxVictories < (maximumVictories + bonusVictories)) {
          maxVictories++;
        } else {
          break;
        }
        totalPoint += opponent.getPoints();
      }
    }
    setPoints(totalPoint);
  }
  
  public boolean keepRank() {
    Integer rankPosition = RepositoryUtils.HASHMAP_MINIMUM_BALANCE.get(rankingCalculate);
    if (getPoints() >= rankPosition.intValue()) {
      setFuturRanking(rankingCalculate);
      return true;
    } else {
      return false;
    }
  }
  
  public void increaseRankingCalculate() {
    if (RankingConstant.RANK_NC.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_40);
    } else if (RankingConstant.RANK_40.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_30_5);
    } else if (RankingConstant.RANK_30_5.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_30_4);
    } else if (RankingConstant.RANK_30_4.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_30_3);
    } else if (RankingConstant.RANK_30_3.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_30_2);
    } else if (RankingConstant.RANK_30_2.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_30_1);
    } else if (RankingConstant.RANK_30_1.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_30);
    } else if (RankingConstant.RANK_30.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_15_5);
    } else if (RankingConstant.RANK_15_5.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_15_4);
    } else if (RankingConstant.RANK_15_4.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_15_3);
    } else if (RankingConstant.RANK_15_3.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_15_2);
    } else if (RankingConstant.RANK_15_2.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_15_1);
    } else if (RankingConstant.RANK_15_1.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_15);
    } else if (RankingConstant.RANK_15.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_5_6);
    } else if (RankingConstant.RANK_5_6.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_4_6);
    } else if (RankingConstant.RANK_4_6.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_3_6);
    } else if (RankingConstant.RANK_3_6.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_2_6);
    } else if (RankingConstant.RANK_2_6.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_1_6);
    } else if (RankingConstant.RANK_1_6.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_0);
    } else if (RankingConstant.RANK_0.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_M_2_6);
    } else if (RankingConstant.RANK_M_2_6.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_M_4_6);
    } else if (RankingConstant.RANK_M_4_6.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_M_15);
    } else if (RankingConstant.RANK_M_15.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_M_30);
    } else if (RankingConstant.RANK_M_30.equals(getRankingCalculate())) {
      setRankingCalculate(RankingConstant.RANK_PROMO);
    }
  }
  
  public void recalculateOpponentPoint() {
    for (Iterator<Opponent> iterator = victories.iterator(); iterator.hasNext();) {
      Opponent opponent = (Opponent) iterator.next();
      int relativePosition = opponent.getRankPosition() - getRankPosition();
      switch (relativePosition) {
      case RankingConstant.VICTORIE_RELATIVE_POSITION_MINUS_3:
        opponent.setPoints(RankingConstant.VICTORIE_POINT_RANK_MINUS_3);
        break;
      case RankingConstant.VICTORIE_RELATIVE_POSITION_MINUS_2:
        opponent.setPoints(RankingConstant.VICTORIE_POINT_RANK_MINUS_2);
        break;
      case RankingConstant.VICTORIE_RELATIVE_POSITION_MINUS_1:
        opponent.setPoints(RankingConstant.VICTORIE_POINT_RANK_MINUS_1);
        break;
      case RankingConstant.VICTORIE_RELATIVE_POSITION_EQUAL:
        opponent.setPoints(RankingConstant.VICTORIE_POINT_RANK_EQUAL);
        break;
      case RankingConstant.VICTORIE_RELATIVE_POSITION_MORE_1:
        opponent.setPoints(RankingConstant.VICTORIE_POINT_RANK_MORE_1);
        break;
      case RankingConstant.VICTORIE_RELATIVE_POSITION_MORE_2:
        opponent.setPoints(RankingConstant.VICTORIE_POINT_RANK_MORE_2);
        break;
      default:
        if (relativePosition < RankingConstant.VICTORIE_RELATIVE_POSITION_MINUS_3) {
          opponent.setPoints(RankingConstant.VICTORIE_POINT_RANK_MINUS_4);
        } else if (relativePosition > RankingConstant.VICTORIE_RELATIVE_POSITION_MORE_2) {
          opponent.setPoints(RankingConstant.VICTORIE_POINT_RANK_MORE_2);
        }
        break;
      }
    }
  }
  
  private void calculDefeats() {
    int sameRank = 0;
    int minusOneRank = 0;
    int minusTwoRank = 0;
    int wo = 0;
    if (defeats != null) {
      for (Iterator<Opponent> iterator = defeats.iterator(); iterator.hasNext();) {
        Opponent opponent = (Opponent) iterator.next();
        if (opponent.isWO()) {
          wo++;
        }
        int relativePosition = opponent.getRankPosition() - getRankPosition();
        switch (relativePosition) {
        case RankingConstant.VICTORIE_RELATIVE_POSITION_MINUS_2:
          minusTwoRank++;
          break;
        case RankingConstant.VICTORIE_RELATIVE_POSITION_MINUS_1:
          minusOneRank++;
          break;
        case RankingConstant.VICTORIE_RELATIVE_POSITION_EQUAL:
          sameRank++;
          break;
        default:
          break;
        }
      }

      if (wo > RankingConstant.MAX_WO_AUTHORIZED) {
        minusTwoRank = minusTwoRank + (wo - RankingConstant.MAX_WO_AUTHORIZED);
      }
    }
    setDefeatsMinusOneRank(minusOneRank);
    setDefeatsMinusTwoRank(minusTwoRank);
    setDefeatsSameRank(sameRank);
  }
  
  private void calculSerie() {
    if (RepositoryUtils.LIST_FOURTH_SERIE.contains(rankingCalculate)) {
      setFourthSerie(true);
      setThirdSerie(false);
      setSecondSerie(false);
      setFirstSerie(false);
    } else if (RepositoryUtils.LIST_THIRD_SERIE.contains(rankingCalculate)) {
      setFourthSerie(false);
      setThirdSerie(true);
      setSecondSerie(false);
      setFirstSerie(false);
    } else if (RepositoryUtils.LIST_SECOND_SERIE.contains(rankingCalculate)) {
      setFourthSerie(false);
      setThirdSerie(false);
      setSecondSerie(true);
      setFirstSerie(false);
    } else {
      setFourthSerie(false);
      setThirdSerie(false);
      setSecondSerie(false);
      setFirstSerie(true);
    }
  }
  
  public void calculatePlayerData() {
    calculateRankPosition();
    calculSerie();
    calculDefeats();
    calculateMaximumVictories();
    calculateBonusVictories();
  }
  
  private int convertVictoriesToBonus(int victories) {
    if (isFourthSerie() && victories >= 0 && victories <= 4) {
      return 1;
    } else if (isFourthSerie() && victories >= 5 && victories <= 9) {
      return 2;
    } else if (isFourthSerie() && victories >= 10 && victories <= 14) {
      return 3;
    } else if (isFourthSerie() && victories >= 15 && victories <= 19) {
      return 4;
    } else if (isFourthSerie() && victories >= 20 && victories <= 24) {
      return 5;
    } else if (isFourthSerie() && victories > 24) {
      return 6;
    } else if (isThirdSerie() && victories >= 0 && victories <= 7) {
      return 1;
    } else if (isThirdSerie() && victories >= 8 && victories <= 14) {
      return 2;
    } else if (isThirdSerie() && victories >= 15 && victories <= 22) {
      return 3;
    } else if (isThirdSerie() && victories >= 23 && victories <= 29) {
      return 4;
    } else if (isThirdSerie() && victories >= 30 && victories <= 39) {
      return 5;
    } else if (isThirdSerie() && victories > 39) {
      return 6;
    } else if (isSecondSerie() && victories <= -81) {
      return -5;
    } else if (isSecondSerie() && victories >= -80 && victories <= -61) {
      return -4;
    } else if (isSecondSerie() && victories >= -60 && victories <= -41) {
      return -3;
    } else if (isSecondSerie() && victories >= -40 && victories <= -31) {
      return -2;
    } else if (isSecondSerie() && victories >= -21 && victories <= -30) {
      return -1;
    } else if (isSecondSerie() && victories >= -20 && victories <= -1) {
      return 0;
    }  else if (isSecondSerie() && victories >= 0 && victories <= 7) {
      return 1;
    } else if (isSecondSerie() && victories >= 8 && victories <= 14) {
      return 2;
    } else if (isSecondSerie() && victories >= 15 && victories <= 22) {
      return 3;
    } else if (isSecondSerie() && victories >= 23 && victories <= 29) {
      return 4;
    } else if (isSecondSerie() && victories >= 30 && victories <= 39) {
      return 5;
    } else if (isSecondSerie() && victories > 39) {
      return 6;
    } else if (isFirstSerie() && victories <= -81) {
      return -5;
    } else if (isFirstSerie() && victories >= -61 && victories <= -80) {
      return -4;
    } else if (isFirstSerie() && victories <= -41) {
      return -3;
    } else if (isFirstSerie() && victories >= -40 && victories <= -31) {
      return -2;
    } else if (isFirstSerie() && victories >= -21 && victories <= -30) {
      return -1;
    } else if (isFirstSerie() && victories >= -20 && victories <= -1) {
      return 0;
    }  else if (isFirstSerie() && victories >= 0 && victories <= 9) {
      return 1;
    } else if (isFirstSerie() && victories >= 10 && victories <= 19) {
      return 2;
    } else if (isFirstSerie() && victories >= 20 && victories <= 24) {
      return 3;
    } else if (isFirstSerie() && victories >= 25 && victories <= 29) {
      return 4;
    } else if (isFirstSerie() && victories >= 30 && victories <= 34) {
      return 5;
    } else if (isFirstSerie() && victories >= 35 && victories <= 44) {
      return 6;
    } else if (isFirstSerie() && victories > 45) {
      return 6;
    }
    return 0;
  }
}
